import org.w3c.dom.Node;

import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;

/**
 * < >类功能说明</ > 
 * @date 2024/11/26 22:33
 * @version V1.0
 * LockFreeRingBuffer类实现了一个无锁的环形缓冲区，支持线程安全的 offer 和 poll 操作。
 * offer 方法将元素添加到缓冲区，poll 方法从缓冲区移除并返回元素。
 * 使用 AtomicReference 和 AtomicIntegerArray 确保线程安全。
 */  
public class LockFreeRingBuffer<T>{
    private final AtomicIntegerArray buffer;
    private final AtomicReference<Node> head;
    private final AtomicReference<Node> tail;
    private final int capacity;

    public LockFreeRingBuffer(int capacity) {
        this.capacity = capacity;
        buffer = new AtomicIntegerArray(capacity);
        head= new AtomicReference<>(new Node(0));
        tail = new AtomicReference<>(new Node(0));
    }

    public boolean offer(T value){
        int valueAsInt = (int) value; // 这里假设传入的值可以转换为int类型，实际应用中可能需要更复杂的转换方式
        Node currentTail;
        Node newTail;
        do{
            currentTail = tail.get();
            int currentTailIndex = currentTail.index;
            int nextIndex = (currentTailIndex+1)%capacity;
            if(nextIndex == head.get().index){
                //缓冲区已满
                return false;
            }
            newTail= new Node(nextIndex);
        }while(!tail.compareAndSet(currentTail,newTail));

        buffer.set(newTail.index,valueAsInt);
        return true;
    }

    public T poll(){
        Node currentHead;
        Node newHead;
        do{
            currentHead = head.get();
            if(currentHead.index == tail.get().index){
                //缓冲区为空
                return null;
            }
            int nextIndex =(currentHead.index+1 )%capacity;
            newHead = new Node(nextIndex);
        }while(!head.compareAndSet(currentHead, newHead));

        int value = buffer.get(newHead.index);
        return (T) Integer.valueOf(value);
        //  这里假设可以转换回原始的类型，实际应用中可能需要更复杂的转换方式
    }

    private static class Node{
        final  int index;

        Node(int index) {
            this.index = index;
        }
    }
}
